package com.mnt.gui.base.buildfactory;

import java.lang.reflect.Field;
import java.util.List;

import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.util.Callback;

import com.mnt.gui.base.buildfactory.annotation.FXTable;
import com.mnt.gui.base.buildfactory.cellhandle.ListCellHandle;

/**
 * table view bind factory
 * <p>
 * 1.support field bind class field<br/>
 * 2.support field convert other field (Button, TextField, ChoiceBox)<br/>
 * </p>
 * 
 * @author 2014-3-25 15:26:16 mnt.cico
 */
public class CellBuildFactory {
	private CellBuildFactory() {

	}

	/**
	 * 
	 * table column bind field whit class
	 * 
	 * @author 2014-3-25 15:26:16 mnt.cico
	 */
	public static <T, M> void buildTableColumn(TableColumn<T, M> tableColumn, String fieldName) {
		tableColumn.setCellValueFactory(new PropertyValueFactory<T, M>(fieldName));
	}

	/**
	 * 
	 * all table column bind class field and set items with table
	 * 
	 * @author 2014-3-25 15:26:16 mnt.cico
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T> void buildTable(Class<T> t, TableView<T> table, ObservableList<T> items) {
		Field[] fields = t.getDeclaredFields();
		List<TableColumn<T, ?>> tableColumns = table.getColumns();
		for (Field field : fields) {
			FXTable tableAnno = field.<FXTable> getAnnotation(FXTable.class);
			if (null != tableAnno) {
				TableColumn<T, ?> tableColumn = tableColumns.get(tableAnno.colIndex());
				if (null != tableColumn) {
					tableColumn.setCellValueFactory(new PropertyValueFactory(field.getName()));
					switch (tableAnno.colType()) {
					case BUTTON:
						buttonType(tableColumn, tableAnno.fieldClass());
						break;
					case TEXTFIELD:
						break;
					case TEXT:
						break;
					case CHECKBOX:
						break;
					case CHOICEBOX:
						break;
					case DATEPRICKER:
						break;
					default:
						break;

					}
				}
			}
		}
		table.setItems(items);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static <T> void buttonType(TableColumn tableColumn, Class<?> c) {
		tableColumn.setCellFactory(new Callback<TableColumn<T, ?>, TableCell<T, ?>>() {

			@Override
			public TableCell<T, ?> call(TableColumn<T, ?> param) {
				return new TableCell() {
					@Override
					protected void updateItem(Object item, boolean empty) {
						super.updateItem(item, empty);
						if (!empty) {
							Button button = new Button(item.toString());
							setGraphic(button);
						}
					}
				};
			}

		});
	}

	/**
	 * get simple table builder tool class 2014-3-29 mnt.cico
	 * 
	 */
	public static <M> TableCellSimpleBuilder<M> getTableCellBuild(TableView<M> tableView, ObservableList<M> tableItem, Class<M> model) {
		return new TableCellSimpleBuilder<M>(tableView, tableItem, model);
	}
	
	
	/**
	 * get normal table builder tool class 2014-11-23 mnt.cico
	 * 
	 */
	public static <M> TableCellNormalBuilder<M> getNormalTableCellBuild(TableView<M> tableView, ObservableList<M> tableItem, Class<M> model) {
		return new TableCellNormalBuilder<M>(tableView, tableItem, model);
	}

	/**
	 * 
	 * 2014年3月31日 mnt.cico
	 * 
	 * @param listView
	 * @param listViewItem
	 * @param node
	 * @param listCellHandle
	 */
	public static <M, N extends Node> void builderListView(ListView<M> listView, ObservableList<M> listViewItem, final Class<N> node,
			final ListCellHandle<M, N> listCellHandle) {
		listView.setItems(listViewItem);
		listView.setCellFactory(new Callback<ListView<M>, ListCell<M>>() {
			@Override
			public ListCell<M> call(ListView<M> param) {
				return new ListCell<M>() {
					@Override
					protected void updateItem(M item, boolean empty) {
						super.updateItem(item, empty);
						if (!empty) {
							try {
								N n = node.newInstance();
								try {
									listCellHandle.execute(item, n);
								} catch (Exception e) {
									listCellHandle.onFailed(e);
								}
								setGraphic(n);
							} catch (InstantiationException e) {
								e.printStackTrace();
							} catch (IllegalAccessException e) {
								e.printStackTrace();
							}

						}
					}
				};
			}
		});

	}
}
